package com.bingxue.edu.management.system.service;

import cn.hutool.crypto.digest.DigestUtil;
import com.bingxue.edu.common.enums.CommonStatusEnum;
import com.bingxue.edu.framework.common.model.PageQuery;
import com.bingxue.edu.framework.common.util.ValidationUtils;
import com.bingxue.edu.framework.mybatis.base.BaseService;
import com.bingxue.edu.framework.mybatis.query.QueryBuilder;
import com.bingxue.edu.management.system.mapper.EmployeeMapper;
import com.bingxue.edu.management.system.mapper.OrgMapper;
import com.bingxue.edu.management.system.model.entity.Employee;
import com.bingxue.edu.management.system.model.entity.Org;
import com.bingxue.edu.management.system.model.query.EmployeeQuery;
import com.bingxue.edu.management.system.model.req.EmployeeCreateReq;
import com.bingxue.edu.management.system.model.resp.EmployeeResp;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

import static com.bingxue.edu.management.system.model.entity.table.EmployeeTableDef.EMPLOYEE;
import static com.bingxue.edu.management.system.model.entity.table.OrgTableDef.ORG;


/**
 * 员工业务实现
 *
 * @author panbo
 * @since 2024-06-28
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EmployeeService extends BaseService<EmployeeMapper, Employee> {

    private final OrgMapper orgMapper;

    public Page<EmployeeResp> getEmployeePage(EmployeeQuery query, PageQuery pageQuery) {
        QueryWrapper queryWrapper = buildQueryWrapper(query);
        return this.getMapper().paginateWithRelationsAs(pageQuery.toPage(), queryWrapper, EmployeeResp.class);
    }

    public List<EmployeeResp> getEmployeeList(EmployeeQuery query) {
        QueryWrapper queryWrapper = buildQueryWrapper(query);
        return this.listAs(queryWrapper, EmployeeResp.class);
    }

    /**
     * 根据用户名查询
     */
    public Employee getByUsername(String username) {
        return this.queryChain().where(EMPLOYEE.USERNAME.eq(username)).one();
    }

    /**
     * 根据手机号查询
     *
     * @param phone 手机号
     * @return 用户信息
     */
    public Employee getByPhone(String phone) {
        return this.queryChain().where(EMPLOYEE.MOBILE_PHONE.eq(phone)).one();
    }


    /**
     * 创建员工
     * 手机号不能重复
     */
    public void createEmployee(EmployeeCreateReq req) {
        Employee employee = this.copy(req);
        employee.setPassword(DigestUtil.bcrypt(req.getPassword()));
        employee.setUsername(employee.getMobilePhone());
        ValidationUtils.throwIfNotNull(this.getByPhone(req.getMobilePhone()),"手机号[{}]已被注册", req.getMobilePhone());
        this.save(employee);
        log.info("创建员工成功, {}", employee);
    }

    /**
     * 修改员工状态
     *
     * @param id 员工id
     */
    public void changeStatus(String id, CommonStatusEnum status) {
        Employee employee = this.getById(id);
        ValidationUtils.throwIfNull(employee, "员工信息不存在");
        employee.setStatus(status);
        this.updateById(employee);
        log.info("修改员工状态成功, {}, {}", id, status);
    }

    /**
     * 重置密码
     * @param id 员工id
     * @param password 密码
     */
    public void resetPassword(String id, String password) {
        Employee employee = this.getById(id);
        ValidationUtils.throwIfNull(employee, "员工信息不存在");
        employee.setPassword(DigestUtil.bcrypt(password));
        employee.setLastPwdModifiedTime(LocalDateTime.now());
        this.updateById(employee);
        log.info("重置员工密码成功, {}, {}", id, password);
    }

    /**
     * 查询组织列表下的员工数量
     */
    public long countByOrgIds(List<String> ids) {
        return this.queryChain().where(EMPLOYEE.ORG_ID.in(ids)).count();
    }

    private QueryWrapper buildQueryWrapper(EmployeeQuery query) {
        if (query.isIncludeSingleOrg() || query.getOrgId() == null) {
            return QueryBuilder.build(query).orderBy(EMPLOYEE.ID, false);
        }
        Org org = orgMapper.selectOneById(query.getOrgId());
        if (org == null) {
            return QueryBuilder.build(query);
        }
        return this.queryChain()
                .leftJoin(ORG).on(ORG.ID.eq(EMPLOYEE.ORG_ID))
                .where(EMPLOYEE.ORG_ID.eq(org.getId()).or(ORG.ANCESTORS.likeLeft(org.getAncestors() + "," + org.getId())))
                .and(EMPLOYEE.TYPE.eq(query.getType()))
                .and(EMPLOYEE.STATUS.eq(query.getStatus()))
                .and(EMPLOYEE.NAME.like(query.getKeyword()).or(EMPLOYEE.MOBILE_PHONE.like(query.getKeyword())))
                .orderBy(EMPLOYEE.ID, false);
    }
}
